1 module hip.util.algorithm; 2 import std.traits:ReturnType; 3 4 5 ReturnType!(Range.front)[] array(Range)(Range range) 6 { 7 static if(__traits(hasMember, Range, "length")) 8 { 9 import hip.util.array; 10 size_t l = range.length; 11 typeof(return) ret = uninitializedArray!(typeof(return))(l); 12 foreach(i; 0..l) 13 ret[i] = range[i]; 14 } 15 else 16 { 17 typeof(return) ret; 18 foreach(v; range) 19 ret~= v; 20 } 21 return ret; 22 } 23 24 25 /** 26 Copies the content of `source` into `target` and returns the 27 remaining (unfilled) part of `target`. 28 29 Preconditions: `target` shall have enough room to accommodate 30 the entirety of `source`. 31 32 Params: 33 source = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) 34 target = an output range 35 36 Returns: 37 The unfilled part of target 38 */ 39 T[] copyInto(T)(T[] source, T[] target) 40 { 41 assert(target.length >= source.length, "Cannot copy source range into a smaller target range."); 42 43 bool overlaps = source.ptr < target.ptr + target.length && target.ptr < source.ptr + source.length; 44 if(overlaps) 45 { 46 if (source.ptr < target.ptr) 47 { 48 foreach_reverse (idx; 0 .. source.length) 49 target[idx] = source[idx]; 50 } 51 else 52 { 53 foreach (idx; 0 .. source.length) 54 target[idx] = source[idx]; 55 } 56 return target[source.length .. target.length]; 57 } 58 else 59 { 60 target[0..source.length] = source[]; 61 return target[source.length..$]; 62 } 63 } 64 65 auto map(Range, From, To)(Range range, scope To delegate (From data) func) 66 { 67 pragma(LDC_no_typeinfo) 68 struct Return 69 { 70 Range inputRange; 71 To delegate(From data) convert; 72 import hip.util.reflection :isArray; 73 static if(isArray!Range) 74 { 75 size_t counter = 0; 76 void popFront(){counter++;} 77 bool empty(){return counter == inputRange.length;} 78 To front(){return convert(inputRange[counter]);} 79 } 80 else 81 { 82 void popFront(){inputRange.popFront;} 83 bool empty(){return inputRange.empty;} 84 To front(){return convert(inputRange.front);} 85 } 86 87 int opApply(scope int delegate(To) dg) 88 { 89 foreach(v; inputRange) 90 { 91 int ret = dg(convert(v)); 92 if(ret) return ret; 93 } 94 return 0; 95 } 96 int opApply(scope int delegate(size_t, To) dg) 97 { 98 size_t i = 0; 99 foreach(v; inputRange) 100 { 101 int ret = dg(i++, convert(v)); 102 if(ret) return ret; 103 } 104 return 0; 105 } 106 } 107 return Return(range, func); 108 } 109 110 void put(Q, T)(Q range, T[] args ...) if(is(T == U*, U)) 111 { 112 int i = 0; 113 foreach(v; range) 114 { 115 if(i >= args.length) 116 return; 117 *args[i] = v; 118 i++; 119 } 120 } 121 122 void swap(T)(ref T a, ref T b) 123 { 124 T tempA = a; 125 a = b; 126 b = tempA; 127 } 128 129 130 int find(T)(in T[] array, scope bool function(T val) pred) 131 { 132 foreach(index, v; array) 133 if(pred(v)) 134 return cast(int)index; 135 return -1; 136 } 137 138 int findLast(T)(in T[] array, scope bool function(T val) pred) 139 { 140 foreach_reverse(index, v; array) 141 if(pred(v)) 142 return cast(int)index; 143 return -1; 144 } 145 146 147 private static void swapElem(T)(ref T lhs, ref T rhs) @safe nothrow @nogc 148 { 149 T tmp = lhs; 150 lhs = rhs; 151 rhs = tmp; 152 } 153 154 155 T[] quicksort(T)(T[] array, scope bool delegate(T a, T b) @nogc nothrow @trusted comparison) nothrow @nogc @trusted 156 { 157 if (array.length < 2) 158 return array; 159 160 static int partition(T* arr, int left, int right, typeof(comparison) comparison) nothrow @nogc @trusted 161 { 162 immutable int mid = left + (right - left) / 2; 163 T pivot = arr[mid]; 164 // move the mid point value to the front. 165 swapElem(arr[mid],arr[left]); 166 int i = left + 1; 167 int j = right; 168 while (i <= j) 169 { 170 while(i <= j && comparison(arr[i], pivot) <= 0 ) 171 i++; 172 173 while(i <= j && comparison(arr[j], pivot) > 0) 174 j--; 175 176 if (i < j) 177 swapElem(arr[i], arr[j]); 178 } 179 swapElem(arr[i - 1], arr[left]); 180 return i - 1; 181 } 182 183 void doQsort(T* array, int left, int right, typeof(comparison) comparison) nothrow @nogc @trusted 184 { 185 if (left >= right) 186 return; 187 188 int part = partition(array, left, right, comparison); 189 doQsort(array, left, part - 1, comparison); 190 doQsort(array, part + 1, right, comparison); 191 } 192 193 doQsort(array.ptr, 0, cast(int)(array.length) - 1, comparison); 194 return array; 195 }